﻿using System;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;

namespace RioStudio.Website
{
    public class ImageHandler : IHttpHandler
    {
        public int _width;
        public int _height;
        public static string noImageUrl = @"~/Content/Images/noimage.png";
        public string imageURL;

        public void ProcessRequest(HttpContext context)
        {
            Bitmap bitOutput;
            Bitmap bitInput = GetImage(context);
            bitInput = RotateFlipImage(context, bitInput);

            if (SetHeightWidth(context, bitInput))
            { bitOutput = ResizeImage(bitInput, _width, _height); }
            else { bitOutput = bitInput; }

            context.Response.Cache.SetExpires(DateTime.Now.Add(new TimeSpan(1, 0, 0)));
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetValidUntilExpires(false);
            context.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0));

            context.Response.ContentType = "image/jpg";
            bitOutput.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);

            return;
        }

        /// <summary>
        /// Get the image requested via the query string.
        /// </summary>
        ///     /// <returns>Return the requested image or the "no image" default if it does not exist.</returns>
        public Bitmap GetImage(HttpContext context)
        {
            Bitmap bitOutput = null;
            try
            {
                var imgUrl = string.Empty;
                if (context.Request["image".ToLower()] != null)
                {
                    imgUrl = context.Request["image".ToLower()].ToString();
                    //imgUrl = imgUrl.Remove(imgUrl.IndexOf("?"), imgUrl.Length - 1);
                }

                if (imgUrl.StartsWith("http://") || imgUrl.StartsWith("https://"))
                {
                    WebRequest req = WebRequest.Create(context.Request.QueryString["image".ToLower()]);
                    WebResponse response = req.GetResponse();
                    Stream stream = response.GetResponseStream();
                    bitOutput = new Bitmap(stream);
                    stream.Close();
                }
                if (imgUrl.StartsWith("/") || imgUrl.StartsWith("~/"))
                {
                    if (imgUrl.StartsWith("/"))
                    {
                        imgUrl = "~" + imgUrl;
                    }

                    if (!File.Exists(context.Server.MapPath(imgUrl)))
                    {
                        bitOutput = new Bitmap(context.Server.MapPath(noImageUrl));
                    }
                    else
                    {
                        bitOutput = new Bitmap(context.Server.MapPath(imgUrl));
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return bitOutput;
        }

        /// <summary>
        /// Set the height and width of the handler class.
        /// </summary>
        /// The context to get the query string <span class="IL_AD" id="IL_AD4">parameters</span>, typically current context.    /// The bitmap that determines the     /// <returns>True if image needs to be resized, false if original dimensions can be kept.</returns>
        public bool SetHeightWidth(HttpContext context, Bitmap bitInput)
        {
            double inputRatio = Convert.ToDouble(bitInput.Width) / Convert.ToDouble(bitInput.Height);

            if (!(String.IsNullOrEmpty(context.Request["width".ToLower()])) && !(String.IsNullOrEmpty(context.Request["height".ToLower()])))
            {
                _width = Int32.Parse(context.Request["width".ToLower()]);
                _height = Int32.Parse(context.Request["height".ToLower()]);
                return true;
            }
            else if (!(String.IsNullOrEmpty(context.Request["width".ToLower()])))
            {
                _width = Int32.Parse(context.Request["width".ToLower()]);
                _height = Convert.ToInt32((_width / inputRatio));
                return true;
            }
            else if (!(String.IsNullOrEmpty(context.Request["height".ToLower()])))
            {
                _height = Int32.Parse(context.Request["height".ToLower()]);
                _width = Convert.ToInt32((_height * inputRatio));
                return true;
            }
            else
            {
                _height = bitInput.Height;
                _width = bitInput.Width;
                return false;
            }
        }

        /// <summary>
        /// Flip or rotate the bitmap according to the query string parameters.
        /// </summary>
        /// The context of the query string parameters.    /// The bitmap to be flipped or rotated.    /// <returns>The bitmap after it has been flipped or rotated.</returns>
        public Bitmap RotateFlipImage(HttpContext context, Bitmap bitInput)
        {
            Bitmap bitOut = bitInput;

            if (String.IsNullOrEmpty(context.Request["RotateFlip"]))
            {
                return bitInput;
            }
            else if (context.Request["RotateFlip"] == "Rotate180flipnone")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate180FlipNone);
            }
            else if (context.Request["RotateFlip"] == "Rotate180flipx")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate180FlipX);
            }
            else if (context.Request["RotateFlip"] == "Rotate180flipxy")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate180FlipXY);
            }
            else if (context.Request["RotateFlip"] == "Rotate180flipy")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate180FlipY);
            }
            else if (context.Request["RotateFlip"] == "Rotate270flipnone")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate270FlipNone);
            }
            else if (context.Request["RotateFlip"] == "Rotate270flipx")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate270FlipX);
            }
            else if (context.Request["RotateFlip"] == "Rotate270FlipXY")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate270FlipXY);
            }
            else if (context.Request["RotateFlip"] == "Rotate270FlipY")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate270FlipY);
            }
            else if (context.Request["RotateFlip"] == "Rotate90FlipNone")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate90FlipNone);
            }
            else if (context.Request["RotateFlip"] == "Rotate90FlipX")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate90FlipX);
            }
            else if (context.Request["RotateFlip"] == "Rotate90FlipXY")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate90FlipXY);
            }
            else if (context.Request["RotateFlip"] == "Rotate90FlipY")
            {
                bitOut.RotateFlip(RotateFlipType.Rotate90FlipY);
            }
            else if (context.Request["RotateFlip"] == "RotateNoneFlipX")
            {
                bitOut.RotateFlip(RotateFlipType.RotateNoneFlipX);
            }
            else if (context.Request["RotateFlip"] == "RotateNoneFlipXY")
            {
                bitOut.RotateFlip(RotateFlipType.RotateNoneFlipXY);
            }
            else if (context.Request["RotateFlip"] == "RotateNoneFlipY")
            {
                bitOut.RotateFlip(RotateFlipType.RotateNoneFlipY);
            }
            else { return bitInput; }

            return bitOut;
        }

        /// <summary>
        /// Resizes bitmap using high quality algorithms.
        /// </summary>
        /// 
        private Bitmap ResizeImage(Bitmap originalImage, int newWidth, int newHeight)
        {
            Bitmap newImage = new Bitmap(originalImage, newWidth, newHeight);

            Graphics g = Graphics.FromImage(newImage);

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(originalImage, 0, 0, newImage.Width, newImage.Height);
            originalImage.Dispose();

            return newImage;
        }

        public bool IsReusable
        {
            get { return false; }
        }
    }
}